#include "Queue_cycle.hpp"
#include <string>
#include <unistd.h>

static int cnt = 1;
Mutex cnt_lock;

template<class T>
class ThreadData{
public:
    ThreadData(const std::string& name, Queue_cycle<T>& queue)
        :_name(name), _pq(&queue)
    {}
    ~ThreadData(){}
    
std::string _name;
Queue_cycle<int>* _pq;
};

template<class T>
void* Productor(void* args){
    ThreadData<T>* ptd = static_cast<ThreadData<T>*>(args);
    while(1){
        // 这里因为有睡眠，即使没有加同步机制页没啥所谓。但是，如果是没有该函数控制
        // 就需要加条件变量 -> 实现同步机制，即公平机制  // 这里就不写了
        sleep(1);
        cnt_lock.Lock();
        std::cout << ptd->_name << "线程生产一个数据 : " << cnt << std::endl;
        ptd->_pq->Push(cnt); 
        ++cnt;
        cnt_lock.UnLock();
    }
}

template<class T>
void* Consumer(void* args){
    ThreadData<T>* ptd = static_cast<ThreadData<T>*>(args);
    while(1){
        sleep(1);
        T data = ptd->_pq->Pop();
        std::cout << ptd->_name << "线程获得了一个数据 : " << data << std::endl; 
    }
}


int main(){
    Queue_cycle<int> queue;
    ThreadData<int>* c_thread1 = new ThreadData<int>(std::string("c_thread_1"), queue);
    ThreadData<int>* c_thread2 = new ThreadData<int>(std::string("c_thread_2"), queue);
    ThreadData<int>* c_thread3 = new ThreadData<int>(std::string("c_thread_3"), queue);
    ThreadData<int>* p_thread1 = new ThreadData<int>(std::string("p_thread_1"), queue);
    ThreadData<int>* p_thread2 = new ThreadData<int>(std::string("p_thread_2"), queue);


    pthread_t consumer1, consumer2, consumer3;
    pthread_t productor1, productor2;

    // 创建线程 
    pthread_create(&consumer1, nullptr, Consumer<int>, c_thread1);
    pthread_create(&consumer2, nullptr, Consumer<int>, c_thread2);
    pthread_create(&consumer3, nullptr, Consumer<int>, c_thread3);
    pthread_create(&productor1, nullptr, Productor<int>, p_thread1);
    pthread_create(&productor2, nullptr, Productor<int>, p_thread2);


    // 等待线程
    pthread_join(consumer1, nullptr);
    pthread_join(consumer2, nullptr);
    pthread_join(consumer3, nullptr);
    pthread_join(productor1, nullptr);
    pthread_join(productor2, nullptr);



    // 析构资源
    delete c_thread1;
    delete c_thread2;
    delete c_thread3;
    delete p_thread1;
    delete p_thread2;



    return 0;
}